package org.jivesoftware.smackx.filetransfer;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Collection;
import java.util.Iterator;
import org.jivesoftware.smack.Connection;
import org.jivesoftware.smack.PacketCollector;
import org.jivesoftware.smack.SmackConfiguration;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.filter.AndFilter;
import org.jivesoftware.smack.filter.FromMatchesFilter;
import org.jivesoftware.smack.filter.PacketFilter;
import org.jivesoftware.smack.filter.PacketIDFilter;
import org.jivesoftware.smack.packet.IQ;
import org.jivesoftware.smack.packet.IQ.Type;
import org.jivesoftware.smack.packet.Packet;
import org.jivesoftware.smack.packet.XMPPError;
import org.jivesoftware.smack.packet.XMPPError.Condition;
import org.jivesoftware.smack.util.StringUtils;
import org.jivesoftware.smackx.packet.Bytestream;
import org.jivesoftware.smackx.packet.Bytestream.Mode;
import org.jivesoftware.smackx.packet.Bytestream.StreamHost;
import org.jivesoftware.smackx.packet.Bytestream.StreamHostUsed;
import org.jivesoftware.smackx.packet.StreamInitiation;

public class Socks5TransferNegotiator extends StreamNegotiator
{
  private static final int CONNECT_FAILURE_THRESHOLD = 2;
  protected static final String NAMESPACE = "http://jabber.org/protocol/bytestreams";
  public static boolean isAllowLocalProxyHost = true;
  private final Connection connection;
  private Socks5TransferNegotiatorManager transferNegotiatorManager;

  public Socks5TransferNegotiator(Socks5TransferNegotiatorManager paramSocks5TransferNegotiatorManager, Connection paramConnection)
  {
    this.connection = paramConnection;
    this.transferNegotiatorManager = paramSocks5TransferNegotiatorManager;
  }

  private void cleanupListeningSocket()
  {
    this.transferNegotiatorManager.removeTransfer();
  }

  private static Bytestream createByteStreamActivate(String paramString1, String paramString2, String paramString3, String paramString4)
  {
    Bytestream localBytestream = new Bytestream(paramString1);
    localBytestream.setMode(null);
    localBytestream.setToActivate(paramString4);
    localBytestream.setFrom(paramString2);
    localBytestream.setTo(paramString3);
    localBytestream.setType(IQ.Type.SET);
    return localBytestream;
  }

  private Bytestream createByteStreamInit(String paramString1, String paramString2, String paramString3, String paramString4, int paramInt)
  {
    Iterator localIterator;
    Bytestream localBytestream = new Bytestream();
    localBytestream.setTo(paramString2);
    localBytestream.setFrom(paramString1);
    localBytestream.setSessionID(paramString3);
    localBytestream.setType(IQ.Type.SET);
    localBytestream.setMode(Bytestream.Mode.tcp);
    if ((paramString4 != null) && (paramInt > 0))
      localBytestream.addStreamHost(paramString1, paramString4, paramInt);
    Collection localCollection = this.transferNegotiatorManager.getStreamHosts();
    if (localCollection != null)
      localIterator = localCollection.iterator();
    while (true)
    {
      if (!(localIterator.hasNext()))
        return localBytestream;
      localBytestream.addStreamHost((Bytestream.StreamHost)localIterator.next());
    }
  }

  private String createDigest(String paramString1, String paramString2, String paramString3)
  {
    return StringUtils.hash(paramString1 + StringUtils.parseName(paramString2) + "@" + StringUtils.parseServer(paramString2) + "/" + StringUtils.parseResource(paramString2) + StringUtils.parseName(paramString3) + "@" + StringUtils.parseServer(paramString3) + "/" + StringUtils.parseResource(paramString3));
  }

  static String createIncomingSocks5Message(InputStream paramInputStream)
    throws IOException
  {
    byte[] arrayOfByte1 = new byte[5];
    paramInputStream.read(arrayOfByte1, 0, 5);
    byte[] arrayOfByte2 = new byte[arrayOfByte1[4]];
    paramInputStream.read(arrayOfByte2, 0, arrayOfByte2.length);
    String str = new String(arrayOfByte2);
    paramInputStream.read();
    paramInputStream.read();
    return str;
  }

  static byte[] createOutgoingSocks5Message(int paramInt, String paramString)
  {
    byte[] arrayOfByte1 = paramString.getBytes();
    byte[] arrayOfByte2 = new byte[7 + arrayOfByte1.length];
    arrayOfByte2[0] = 5;
    arrayOfByte2[1] = (byte)paramInt;
    arrayOfByte2[2] = 0;
    arrayOfByte2[3] = 3;
    arrayOfByte2[4] = (byte)arrayOfByte1.length;
    System.arraycopy(arrayOfByte1, 0, arrayOfByte2, 5, arrayOfByte1.length);
    arrayOfByte2[(arrayOfByte2.length - 2)] = 0;
    arrayOfByte2[(arrayOfByte2.length - 1)] = 0;
    return arrayOfByte2;
  }

  private Bytestream createUsedHostConfirmation(Bytestream.StreamHost paramStreamHost, String paramString1, String paramString2, String paramString3)
  {
    Bytestream localBytestream = new Bytestream();
    localBytestream.setTo(paramString1);
    localBytestream.setFrom(paramString2);
    localBytestream.setType(IQ.Type.RESULT);
    localBytestream.setPacketID(paramString3);
    localBytestream.setUsedHost(paramStreamHost.getJID());
    return localBytestream;
  }

  private String discoverLocalIP()
    throws UnknownHostException
  {
    return InetAddress.getLocalHost().getHostAddress();
  }

  private Socks5TransferNegotiatorManager.ProxyProcess establishListeningSocket()
    throws IOException
  {
    return this.transferNegotiatorManager.addTransfer();
  }

  private void establishSOCKS5ConnectionToProxy(Socket paramSocket, String paramString)
    throws IOException
  {
    byte[] arrayOfByte = new byte[3];
    arrayOfByte[0] = 5;
    arrayOfByte[1] = 1;
    arrayOfByte[2] = 0;
    DataOutputStream localDataOutputStream = new DataOutputStream(paramSocket.getOutputStream());
    localDataOutputStream.write(arrayOfByte);
    DataInputStream localDataInputStream = new DataInputStream(paramSocket.getInputStream());
    localDataInputStream.read(new byte[2]);
    localDataOutputStream.write(createOutgoingSocks5Message(1, paramString));
    createIncomingSocks5Message(localDataInputStream);
  }

  private int getConnectionFailures(String paramString)
  {
    return this.transferNegotiatorManager.getConnectionFailures(paramString);
  }

  private void incrementConnectionFailures(String paramString)
  {
    this.transferNegotiatorManager.incrementConnectionFailures(paramString);
  }

  // ERROR //
  private Socket initBytestreamSocket(String paramString1, String paramString2, String paramString3)
    throws java.lang.Exception
  {
    // Byte code:
    //   0: aload_0
    //   1: invokespecial 256	org/jivesoftware/smackx/filetransfer/Socks5TransferNegotiator:establishListeningSocket	()Lorg/jivesoftware/smackx/filetransfer/Socks5TransferNegotiatorManager$ProxyProcess;
    //   4: astore 13
    //   6: aload 13
    //   8: astore 5
    //   10: aload_0
    //   11: invokespecial 258	org/jivesoftware/smackx/filetransfer/Socks5TransferNegotiator:discoverLocalIP	()Ljava/lang/String;
    //   14: astore 12
    //   16: aload 12
    //   18: astore 8
    //   20: aload 5
    //   22: ifnull +67 -> 89
    //   25: aload 5
    //   27: invokevirtual 263	org/jivesoftware/smackx/filetransfer/Socks5TransferNegotiatorManager$ProxyProcess:getPort	()I
    //   30: istore 9
    //   32: aload_0
    //   33: aload_2
    //   34: aload_3
    //   35: aload_1
    //   36: aload 8
    //   38: iload 9
    //   40: invokespecial 265	org/jivesoftware/smackx/filetransfer/Socks5TransferNegotiator:createByteStreamInit	(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;I)Lorg/jivesoftware/smackx/packet/Bytestream;
    //   43: astore 10
    //   45: aload_0
    //   46: aload_1
    //   47: aload 5
    //   49: aload_0
    //   50: aload_1
    //   51: aload_2
    //   52: aload_3
    //   53: invokespecial 267	org/jivesoftware/smackx/filetransfer/Socks5TransferNegotiator:createDigest	(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
    //   56: aload 10
    //   58: invokespecial 271	org/jivesoftware/smackx/filetransfer/Socks5TransferNegotiator:waitForUsedHostResponse	(Ljava/lang/String;Lorg/jivesoftware/smackx/filetransfer/Socks5TransferNegotiatorManager$ProxyProcess;Ljava/lang/String;Lorg/jivesoftware/smackx/packet/Bytestream;)Lorg/jivesoftware/smackx/filetransfer/Socks5TransferNegotiator$SelectedHostInfo;
    //   61: getfield 275	org/jivesoftware/smackx/filetransfer/Socks5TransferNegotiator$SelectedHostInfo:establishedSocket	Ljava/net/Socket;
    //   64: astore 11
    //   66: aload_0
    //   67: invokespecial 277	org/jivesoftware/smackx/filetransfer/Socks5TransferNegotiator:cleanupListeningSocket	()V
    //   70: aload 11
    //   72: areturn
    //   73: astore 4
    //   75: aconst_null
    //   76: astore 5
    //   78: goto -68 -> 10
    //   81: astore 7
    //   83: aconst_null
    //   84: astore 8
    //   86: goto -66 -> 20
    //   89: iconst_0
    //   90: istore 9
    //   92: goto -60 -> 32
    //   95: astore 6
    //   97: aload_0
    //   98: invokespecial 277	org/jivesoftware/smackx/filetransfer/Socks5TransferNegotiator:cleanupListeningSocket	()V
    //   101: aload 6
    //   103: athrow
    //
    // Exception table:
    //   from	to	target	type
    //   0	6	73	IOException
    //   10	16	81	UnknownHostException
    //   10	16	95	finally
    //   25	66	95	finally
  }

  private SelectedHostInfo selectHost(Bytestream paramBytestream)
    throws XMPPException
  {
    String str;
    Socket localSocket;
    Iterator localIterator = paramBytestream.getStreamHosts().iterator();
    Bytestream.StreamHost localStreamHost = null;
    Object localObject1 = null;
    do
    {
      if (!(localIterator.hasNext()))
      {
        if ((localStreamHost != null) && (localObject1 != null) && (localObject1.isConnected()))
          break;
        throw new XMPPException("Could not establish socket with any provided host", new XMPPError(XMPPError.Condition.no_acceptable, "Could not establish socket with any provided host"));
      }
      localStreamHost = (Bytestream.StreamHost)localIterator.next();
      str = localStreamHost.getAddress();
    }
    while (getConnectionFailures(str) >= 2);
    try
    {
      localSocket = new Socket(str, localStreamHost.getPort());
    }
    catch (IOException localIOException2)
    {
      Object localObject2;
      try
      {
        while (true)
        {
          while (true)
          {
            establishSOCKS5ConnectionToProxy(localSocket, createDigest(paramBytestream.getSessionID(), paramBytestream.getFrom(), paramBytestream.getTo()));
            localObject1 = localSocket;
          }
          localIOException2 = localIOException2;
          localObject2 = localIOException2;
          ((IOException)localObject2).printStackTrace();
          incrementConnectionFailures(str);
          localStreamHost = null;
          localObject1 = null;
        }
        return new SelectedHostInfo(localStreamHost, localObject1);
      }
      catch (IOException localIOException1)
      {
        localObject2 = localIOException1;
      }
    }
  }

  private SelectedHostInfo waitForUsedHostResponse(String paramString1, Socks5TransferNegotiatorManager.ProxyProcess paramProxyProcess, String paramString2, Bytestream paramBytestream)
    throws XMPPException, IOException
  {
    Bytestream localBytestream1;
    SelectedHostInfo localSelectedHostInfo2;
    SelectedHostInfo localSelectedHostInfo1 = new SelectedHostInfo();
    PacketCollector localPacketCollector1 = this.connection.createPacketCollector(new PacketIDFilter(paramBytestream.getPacketID()));
    this.connection.sendPacket(paramBytestream);
    Packet localPacket = localPacketCollector1.nextResult(10000L);
    localPacketCollector1.cancel();
    if ((localPacket != null) && (localPacket instanceof Bytestream))
    {
      localBytestream1 = (Bytestream)localPacket;
      if (!(localBytestream1.getType().equals(IQ.Type.ERROR)))
        break label115;
      throw new XMPPException("Remote client returned error, stream hosts expected", localBytestream1.getError());
    }
    throw new XMPPException("Unexpected response from remote user");
    label115: Bytestream.StreamHostUsed localStreamHostUsed = localBytestream1.getUsedHost();
    Bytestream.StreamHost localStreamHost = paramBytestream.getStreamHost(localStreamHostUsed.getJID());
    if (localStreamHost == null)
      throw new XMPPException("Remote user responded with unknown host");
    if (localStreamHostUsed.getJID().equals(paramBytestream.getFrom()))
    {
      localSelectedHostInfo1.establishedSocket = paramProxyProcess.getSocket(paramString2);
      localSelectedHostInfo1.selectedHost = localStreamHost;
      localSelectedHostInfo2 = localSelectedHostInfo1;
    }
    while (true)
    {
      while (true)
      {
        return localSelectedHostInfo2;
        localSelectedHostInfo1.establishedSocket = new Socket(localStreamHost.getAddress(), localStreamHost.getPort());
        establishSOCKS5ConnectionToProxy(localSelectedHostInfo1.establishedSocket, paramString2);
        Bytestream localBytestream2 = createByteStreamActivate(paramString1, localBytestream1.getTo(), localStreamHost.getJID(), localBytestream1.getFrom());
        PacketCollector localPacketCollector2 = this.connection.createPacketCollector(new PacketIDFilter(localBytestream2.getPacketID()));
        this.connection.sendPacket(localBytestream2);
        IQ localIQ = (IQ)localPacketCollector2.nextResult(SmackConfiguration.getPacketReplyTimeout());
        localPacketCollector2.cancel();
        if (localIQ.getType().equals(IQ.Type.RESULT))
          break;
        localSelectedHostInfo1.establishedSocket.close();
        localSelectedHostInfo2 = null;
      }
      localSelectedHostInfo2 = localSelectedHostInfo1;
    }
  }

  public void cleanup()
  {
  }

  public InputStream createIncomingStream(StreamInitiation paramStreamInitiation)
    throws XMPPException
  {
    return negotiateIncomingStream(initiateIncomingStream(this.connection, paramStreamInitiation));
  }

  // ERROR //
  public OutputStream createOutgoingStream(String paramString1, String paramString2, String paramString3)
    throws XMPPException
  {
    // Byte code:
    //   0: aload_0
    //   1: aload_1
    //   2: aload_2
    //   3: aload_3
    //   4: invokespecial 427	org/jivesoftware/smackx/filetransfer/Socks5TransferNegotiator:initBytestreamSocket	(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Ljava/net/Socket;
    //   7: astore 5
    //   9: aload 5
    //   11: ifnull +50 -> 61
    //   14: new 429	java/io/BufferedOutputStream
    //   17: dup
    //   18: aload 5
    //   20: invokevirtual 219	java/net/Socket:getOutputStream	()Ljava/io/OutputStream;
    //   23: invokespecial 430	java/io/BufferedOutputStream:<init>	(Ljava/io/OutputStream;)V
    //   26: astore 6
    //   28: aload 6
    //   30: areturn
    //   31: astore 4
    //   33: new 281	XMPPException
    //   36: dup
    //   37: ldc_w 432
    //   40: aload 4
    //   42: invokespecial 435	XMPPException:<init>	(Ljava/lang/String;Ljava/lang/Throwable;)V
    //   45: athrow
    //   46: astore 7
    //   48: new 281	XMPPException
    //   51: dup
    //   52: ldc_w 437
    //   55: aload 7
    //   57: invokespecial 435	XMPPException:<init>	(Ljava/lang/String;Ljava/lang/Throwable;)V
    //   60: athrow
    //   61: aconst_null
    //   62: astore 6
    //   64: goto -36 -> 28
    //
    // Exception table:
    //   from	to	target	type
    //   0	9	31	java.lang.Exception
    //   14	28	46	IOException
  }

  public PacketFilter getInitiationPacketFilter(String paramString1, String paramString2)
  {
    PacketFilter[] arrayOfPacketFilter = new PacketFilter[2];
    arrayOfPacketFilter[0] = new FromMatchesFilter(paramString1);
    arrayOfPacketFilter[1] = new BytestreamSIDFilter(paramString2);
    return new AndFilter(arrayOfPacketFilter);
  }

  public String[] getNamespaces()
  {
    String[] arrayOfString = new String[1];
    arrayOfString[0] = "http://jabber.org/protocol/bytestreams";
    return arrayOfString;
  }

  // ERROR //
  InputStream negotiateIncomingStream(Packet paramPacket)
    throws XMPPException
  {
    // Byte code:
    //   0: aload_1
    //   1: checkcast 45	org/jivesoftware/smackx/packet/Bytestream
    //   4: astore_2
    //   5: aload_2
    //   6: invokevirtual 359	org/jivesoftware/smackx/packet/Bytestream:getType	()Lorg/jivesoftware/smack/packet/IQ$Type;
    //   9: getstatic 362	org/jivesoftware/smack/packet/IQ$Type:ERROR	Lorg/jivesoftware/smack/packet/IQ$Type;
    //   12: invokevirtual 368	java/lang/Object:equals	(Ljava/lang/Object;)Z
    //   15: ifeq +15 -> 30
    //   18: new 281	XMPPException
    //   21: dup
    //   22: aload_2
    //   23: invokevirtual 374	org/jivesoftware/smackx/packet/Bytestream:getError	()Lorg/jivesoftware/smack/packet/XMPPError;
    //   26: invokespecial 455	XMPPException:<init>	(Lorg/jivesoftware/smack/packet/XMPPError;)V
    //   29: athrow
    //   30: aload_0
    //   31: aload_2
    //   32: invokespecial 457	org/jivesoftware/smackx/filetransfer/Socks5TransferNegotiator:selectHost	(Lorg/jivesoftware/smackx/packet/Bytestream;)Lorg/jivesoftware/smackx/filetransfer/Socks5TransferNegotiator$SelectedHostInfo;
    //   35: astore 5
    //   37: aload_0
    //   38: aload 5
    //   40: getfield 399	org/jivesoftware/smackx/filetransfer/Socks5TransferNegotiator$SelectedHostInfo:selectedHost	Lorg/jivesoftware/smackx/packet/Bytestream$StreamHost;
    //   43: aload_2
    //   44: invokevirtual 315	org/jivesoftware/smackx/packet/Bytestream:getFrom	()Ljava/lang/String;
    //   47: aload_2
    //   48: invokevirtual 318	org/jivesoftware/smackx/packet/Bytestream:getTo	()Ljava/lang/String;
    //   51: aload_2
    //   52: invokevirtual 333	org/jivesoftware/smackx/packet/Bytestream:getPacketID	()Ljava/lang/String;
    //   55: invokespecial 459	org/jivesoftware/smackx/filetransfer/Socks5TransferNegotiator:createUsedHostConfirmation	(Lorg/jivesoftware/smackx/packet/Bytestream$StreamHost;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Lorg/jivesoftware/smackx/packet/Bytestream;
    //   58: astore 6
    //   60: aload_0
    //   61: getfield 33	org/jivesoftware/smackx/filetransfer/Socks5TransferNegotiator:connection	Lorg/jivesoftware/smack/Connection;
    //   64: aload 6
    //   66: invokevirtual 344	org/jivesoftware/smack/Connection:sendPacket	(Lorg/jivesoftware/smack/packet/Packet;)V
    //   69: new 461	java/io/PushbackInputStream
    //   72: dup
    //   73: aload 5
    //   75: getfield 275	org/jivesoftware/smackx/filetransfer/Socks5TransferNegotiator$SelectedHostInfo:establishedSocket	Ljava/net/Socket;
    //   78: invokevirtual 233	java/net/Socket:getInputStream	()Ljava/io/InputStream;
    //   81: invokespecial 462	java/io/PushbackInputStream:<init>	(Ljava/io/InputStream;)V
    //   84: astore 7
    //   86: aload 7
    //   88: aload 7
    //   90: invokevirtual 463	java/io/PushbackInputStream:read	()I
    //   93: invokevirtual 467	java/io/PushbackInputStream:unread	(I)V
    //   96: aload 7
    //   98: areturn
    //   99: astore_3
    //   100: aload_3
    //   101: invokevirtual 470	XMPPException:getXMPPError	()Lorg/jivesoftware/smack/packet/XMPPError;
    //   104: ifnull +34 -> 138
    //   107: aload_0
    //   108: aload_2
    //   109: invokevirtual 318	org/jivesoftware/smackx/packet/Bytestream:getTo	()Ljava/lang/String;
    //   112: aload_2
    //   113: invokevirtual 315	org/jivesoftware/smackx/packet/Bytestream:getFrom	()Ljava/lang/String;
    //   116: aload_2
    //   117: invokevirtual 333	org/jivesoftware/smackx/packet/Bytestream:getPacketID	()Ljava/lang/String;
    //   120: aload_3
    //   121: invokevirtual 470	XMPPException:getXMPPError	()Lorg/jivesoftware/smack/packet/XMPPError;
    //   124: invokespecial 474	org/jivesoftware/smackx/filetransfer/StreamNegotiator:createError	(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lorg/jivesoftware/smack/packet/XMPPError;)Lorg/jivesoftware/smack/packet/IQ;
    //   127: astore 4
    //   129: aload_0
    //   130: getfield 33	org/jivesoftware/smackx/filetransfer/Socks5TransferNegotiator:connection	Lorg/jivesoftware/smack/Connection;
    //   133: aload 4
    //   135: invokevirtual 344	org/jivesoftware/smack/Connection:sendPacket	(Lorg/jivesoftware/smack/packet/Packet;)V
    //   138: aload_3
    //   139: athrow
    //   140: astore 8
    //   142: new 281	XMPPException
    //   145: dup
    //   146: ldc_w 476
    //   149: aload 8
    //   151: invokespecial 435	XMPPException:<init>	(Ljava/lang/String;Ljava/lang/Throwable;)V
    //   154: athrow
    //
    // Exception table:
    //   from	to	target	type
    //   30	37	99	XMPPException
    //   69	96	140	IOException
  }

  private static class BytestreamSIDFilter
  implements PacketFilter
  {
    private String sessionID;

    public BytestreamSIDFilter(String paramString)
    {
      if (paramString == null)
        throw new IllegalArgumentException("StreamID cannot be null");
      this.sessionID = paramString;
    }

    public boolean accept(Packet paramPacket)
    {
      int i;
      if (!(Bytestream.class.isInstance(paramPacket)))
        i = 0;
      while (true)
      {
        while (true)
        {
          return i;
          String str = ((Bytestream)paramPacket).getSessionID();
          if ((str == null) || (!(str.equals(this.sessionID))))
            break;
          i = 1;
        }
        i = 0;
      }
    }
  }

  private static class SelectedHostInfo
  {
    protected Socket establishedSocket;
    protected XMPPException exception;
    protected Bytestream.StreamHost selectedHost;

    SelectedHostInfo(Bytestream.StreamHost paramStreamHost, Socket paramSocket)
    {
      this.selectedHost = paramStreamHost;
      this.establishedSocket = paramSocket;
    }
  }
}